package server.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import server.config.TaskPoolConfig;
import server.config.exception.BizException;
import server.dao.AccountDao;
import server.dao.DyLogDao;
import server.dao.MoneyRecordDao;
import server.model.entity.Account;
import server.model.entity.DyLog;
import server.model.entity.MoneyRecord;
import server.service.MoneyRecordService;
import server.tool.ClientAgent;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

/**
 * @description:
 * @author: 许哲
 * @createTime: 2021/11/22 18:17
 * @version: 1.0
 */
@Service
public class MoneyRecordServiceImpl implements MoneyRecordService {
    @Autowired
    @Qualifier(value = "taskExecutor")
    private ThreadPoolTaskExecutor taskPoolConfig;

    @Autowired
    private MoneyRecordDao moneyRecordDao;

    @Autowired
    private DyLogDao dyLogDao;

    @Autowired
    private AccountDao accountDao;

    @Override
    public void instanceMoneyRecord(MoneyRecord moneyRecord) {
        Account ac = accountDao.findByAccount(moneyRecord.getDyAccount());
        taskPoolConfig.execute(() -> {
            try {
                userPackAgeData(ac,accountDao,moneyRecord, moneyRecordDao, dyLogDao, ac.getCookie());
            } catch (InterruptedException e) {
                throw new BizException("失败");
            }
        });
    }

    @Async("taskExecutor")
    public void userPackAgeData(Account ac,AccountDao acDao,MoneyRecord moneyRecord, MoneyRecordDao recordDao, DyLogDao logDao, String cookie) throws InterruptedException {
        final long NANOSEC_PER_SEC = 1000l * 1000 * 1000;
        long startTime = System.nanoTime();
        Map<String, String> mp = new HashMap<>();
        mp.put("scene", "pc");
        int rom = new Random().nextInt(new ClientAgent().getUA().size());
        mp.put("risk_info", "{\"user_agent\":\"" + new ClientAgent().getUA().get(rom) + "\"}");
        mp.put("process", moneyRecord.getCache());
        mp.put("biz_content", "{\"trade_no\":\"" + moneyRecord.getDyOrder() + "\"}");
        JSONObject jon = new JSONObject();
        while ((System.nanoTime() - startTime) < 5 * 60 * NANOSEC_PER_SEC) {
            Thread.sleep(60000);
            jon = JSON.parseObject(http("https://tp-pay.snssdk.com/gateway-cashier/tp.cashier.trade_query", mp, cookie));
            DyLog log = new DyLog();
            log.setDyOrder(moneyRecord.getDyOrder());
            log.setLog(JSON.toJSONString(jon));
            log.setSystemCode(moneyRecord.getSystemCode());
            logDao.save(log);
            if (jon.get("error") == null || jon.getString("error").equalsIgnoreCase("null")) {
                JSONObject tradeInfo = jon.getJSONObject("data").getJSONObject("trade_info");
                if (tradeInfo.getString("status").equalsIgnoreCase("SUCCESS")) {
                    moneyRecord.setStatus(MoneyRecord.STATUS.SUCCESS);
                    recordDao.save(moneyRecord);
                    ac.setIngMoney(ac.getIngMoney().subtract(moneyRecord.getMoney()));
                    ac.setHistoryMoney(ac.getHistoryMoney().add(moneyRecord.getMoney()));
                    acDao.save(ac);
                    Thread.currentThread().interrupt();
                    return;
                }
                if (tradeInfo.getString("status").equalsIgnoreCase("TIMEOUT")) {
                    moneyRecord.setStatus(MoneyRecord.STATUS.TIMEOUT);
                    recordDao.save(moneyRecord);
                    Thread.currentThread().interrupt();
                    return;
                }
            } else {
                moneyRecord.setStatus(MoneyRecord.STATUS.ERROR);
                recordDao.save(moneyRecord);
                Thread.currentThread().interrupt();
                return;
            }
        }
        moneyRecord.setStatus(MoneyRecord.STATUS.TIMEOUT);
        recordDao.save(moneyRecord);
        Thread.currentThread().interrupt();
        return;
    }

    public static String http(String url, Map<String, String> params, String cookie) {
        URL u = null;
        HttpURLConnection con = null;
        // 构建请求参数
        StringBuffer sb = new StringBuffer();
        if (params != null) {
            for (Map.Entry<String, String> e : params.entrySet()) {
                sb.append(e.getKey());
                sb.append("=");
                sb.append(e.getValue());
                sb.append("&");
            }
            sb.substring(0, sb.length() - 1);
        }
        System.out.println("send_url:" + url);
        System.out.println("send_data:" + sb.toString());
        // 尝试发送请求
        try {
            u = new URL(url);
            con = (HttpURLConnection) u.openConnection();
            //// POST 只能为大写，严格限制，post会不识别
            con.setRequestMethod("POST");
            int rom = new Random().nextInt(new ClientAgent().getUA().size());
            con.setRequestProperty("User-Agent", new ClientAgent().getUA().get(rom));
            con.setRequestProperty("Cookie", cookie);
            con.setDoOutput(true);
            con.setDoInput(true);
            con.setUseCaches(false);
            con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream(), "UTF-8");
            osw.write(sb.toString());
            osw.flush();
            osw.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (con != null) {
                con.disconnect();
            }
        }

        // 读取返回内容
        StringBuffer buffer = new StringBuffer();
        try {
            //一定要有返回值，否则无法把请求发送给server端。
            BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
            String temp;
            while ((temp = br.readLine()) != null) {
                buffer.append(temp);
                buffer.append("\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return buffer.toString();
    }
}
